#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <thread>
#include <sys/socket.h>
#include <string>
#include <opencv2/opencv.hpp>
#include "main.h"
#include "videoio_client.h"
#include "detect_client.h"
#include "track.h"

using namespace cv;
using namespace std;

// 各任务进行状态序号
int idxInputImage = 0;  // image index of input video
int idxOutputImage = 0; // image index of output video
int idxShowImage = 0;	// 目标追踪下一帧要处理的对象
int Frame_cnt = 0;      // 视频总长度
bool bReading = true;   // flag of input
bool bDetecting = true; // 目标检测进程状态
double Time_video = 0;  // 整个视频追踪所花的时间

// 多线程控制相关
mutex mtxQueueInput_client;        		  // mutex of input queue client
queue<pair<int, Mat>> queueInput_client;  // input queue client
mutex mtxQueueShow;                // mutex of display queue
priority_queue<imageout_idx, vector<imageout_idx>, paircomp> queueShow;  // display queue 目标追踪的输入
mutex mtxQueueOutput;			  // mutex of output queue client 最终输出
queue<Mat> queueOutput;  		   		  // output queue 目标追踪输出队列

// 文件路径
const char* SAVE_PATH = "../res/Track_res.mp4";
const char src[30] = "../data/PRC_9resize.mp4";
// const char src[30] = "../data/infrared_640.jpg";


void error_handling(const char *message);
double what_time_is_it_now();

int main(int argc, char* argv[])
{
	int sock_tcp[SOCKETNUM];
	char message[30];
	int str_len;
	
	if(argc!=4){
		printf("Usage : %s <IP1> <IP2> <port>\n", argv[0]);
		exit(1);
	}
	
	for(int i=0;i<SOCKETNUM;i++){
		sock_tcp[i] = socket(PF_INET, SOCK_STREAM, 0);
		struct sockaddr_in serv_addr;
		if(sock_tcp[i] == -1)
			error_handling("socket() error");
		memset(&serv_addr, 0, sizeof(serv_addr));
		serv_addr.sin_family=AF_INET;
		serv_addr.sin_addr.s_addr=inet_addr(argv[i+1]);
		serv_addr.sin_port=htons(atoi(argv[SOCKETNUM+1]));
		if(connect(sock_tcp[i], (struct sockaddr*)&serv_addr, sizeof(serv_addr))==-1) 
			error_handling("connect() error!");
	}
	//---------------------------TCP建立连接----------------------------------
	const int thread_num = 4;
	array<thread, thread_num> threads;
	threads = {
					//只使用一个的进程 传入cpu_id
					thread(videoTransClient, src, 0, sock_tcp),
					thread(get_detections, 1, sock_tcp),
					thread(track_process, 2),
					thread(videoWrite, 3)
				};
	for (int i = 0; i < thread_num; i++)
		threads[i].join();

	
	for(int i=0;i<SOCKETNUM;i++){
		close(sock_tcp[i]);
	}
	return 0;
}

void error_handling(const char *message)
{
	fputs(message, stderr);
	fputc('\n', stderr);
	exit(1);
}

double what_time_is_it_now()
{
	// 单位: ms
    struct timeval time;
    if (gettimeofday(&time,NULL)){
        return 0;
    }
    return (double)time.tv_sec * 1000 + (double)time.tv_usec * .001;
}